<?php

/**
 * AuditableBehavior
 * 
 * Comportamiento que mantiene un log de la actividad realizada en los modelos auditados
 * guardando un registros de las altas, bajas y ediciones realizadas, manteniendo los datos
 * editados y el usuario que realiza la modificación, utiliza la tabla Actividades, 
 * la actividad de dicho modelo no es auditable, para ello 'auditar' => false
 *
 * @author Javier Melero <jmelero at linkedsc.com.ar>
 */
class AuditableBehavior extends ModelBehavior {

    /**
     * Modelos a los que no hay q auditar
     * 
     * @var array 
     */
    public $blacklist = array(
        'Aco',
        'Aro',
        'AclNode',
        'AcoAction',
        'Permission'
    );

    /**
     * Define si es que hay que auditar este modelo o no
     * @param Model $model
     * @return boolean 
     */
    private function auditar(Model $model) {
        return ($this->settings[$model->alias]['auditar']
                and !in_array(get_class($model), $this->blacklist));
    }

    /**
     *
     * @param Model $Model
     * @param array $config 
     */
    public function setup(&$Model, $config = array()) {
        if (!isset($this->settings[$Model->alias])) {
            $this->settings[$Model->alias] = array(
                'auditar' => true
            );
        }
        $this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], (array) $config);
    }

    /**
     * Antes de guardar cambios guardamos la información anterior 
     * 
     * @param Model $model 
     * @return boolean Siempre true
     */
    public function beforeSave(Model $model) {
        if (!$this->auditar($model))
            return true;
        // clonamos el objeto, porq al hacer un read(), pisamos el $model->data
        // el id del objeto se copia, asi que con read() alcanza
        $clon = clone $model;
        $clon->recursive = -1;
        // guardamos solo la info del modelo en cuestion, no los vinculados
        // tenemos que volver a leer la información, porq lo que tenemos en data es nuevo
        $this->settings[$model->alias]['object'] = $clon->read();
        return true;
    }

    /**
     *
     * @param Model $model
     * @param boolean $created 
     * @return boolean Siempre true
     */
    public function afterSave(Model $model, $created) {
        if (!$this->auditar($model))
            return true;

        //$Actividad = new Actividad();
        App::import('Model', 'Activity');
        $Actividad = new Activity();

        $actividad = array(
            //'tipo' => 'create',
            'type' => 'create',
            //'registro' => get_class($model) . '.' . $model->id,
            'register' => get_class($model) . '.' . $model->id,
            //'user_id' => AuthComponent::user('id'),
            'user_id' => $_SESSION['Auth']['User']['id'],
            //'usuario_id' => 1, //MARIANO, SACAR ESTO UNA VEZ QUE ESTE PUESTO EL AUTH COMPONENT
            //'fecha_hora' => date('Y-m-d H:i:s')
            'date_time' => date('Y-m-d H:i:s')
        );

        // en caso de ser una edición y que tengamos datos del estado anterior, los guardamos
        if (!$created) {
            //$actividad['tipo'] = 'update';
            $actividad['type'] = 'update';
            if (isset($this->settings[$model->alias]['object'])) {
                //$actividad['estado_anterior'] = serialize($this->settings[$model->alias]['object']);
                $actividad['status_before'] = serialize($this->settings[$model->alias]['object']);
                unset($this->settings[$model->alias]['object']);
            }
        }
        
        $Actividad->create();
        if (!$Actividad->save($actividad)) {
            /**
             * @todo hacer algo sino se pudo guardar
             */
        }
        return true;
    }

    /**
     *
     * @param Model $model
     * @param boolean $cascade
     * @return boolean 
     */
    public function beforeDelete($model, $cascade = true) {
        if (!$this->auditar($model))
            return true;

        $clon = clone $model;
        if (empty($clon->data) and isset($clon->id))
            $clon->read();

        if (!empty($clon->data)) {
            // guardamos solo la info del clono en cuestion, no los vinculados
            $this->settings[$clon->alias]['object'] = $clon->data[$clon->alias];
            $this->settings[$clon->alias]['id'] = $clon->data[$clon->alias][$clon->primaryKey];
        }
        return true;
    }

    /**
     *
     * @param Model $model
     * @return boolean 
     */
    public function afterDelete($model) {
        if (!$this->auditar($model))
            return true;

//        App::uses('Actividad', 'Model');
//        $Actividad = new Actividad();
        //App::uses('Activity', 'Model');
        App::import('Model', 'Activity');
        $Actividad = new Activity();

        $id = $model->id;
        if (!$id and isset($this->settings[$model->alias]['id']))
            $id = $this->settings[$model->alias]['id'];

        $actividad = array(
            //'tipo' => 'delete',
            'type' => 'delete',
            //'registro' => get_class($model) . '.' . $id,
            'register' => get_class($model) . '.' . $id,
            'usuario_id' => $_SESSION['Auth']['User']['id'],
            //'usuario_id' => AuthComponent::user('id'),
            //'usuario_id' => 1, //MARIANO, SACAR ESTO UNA VEZ QUE ESTE PUESTO EL AUTH COMPONENT
            //'fecha_hora' => date('Y-m-d H:i:s')
            'date_time' => date('Y-m-d H:i:s')
        );
        $Actividad->create();
        if (!$Actividad->save($actividad)) {
            /**
             * @todo hacer algo sino se pudo guardar
             */
        }
        return true;
    }

    /**
     * Ante un error eliminamos los datos del objeto y no guardamos nada
     * 
     * @param Model $model
     * @param string $error 
     */
    public function onError($model, $error) {
        if (isset($this->settings[$model->alias]['object']))
            unset($this->settings[$model->alias]['object']);
        if (isset($this->settings[$model->alias]['id']))
            unset($this->settings[$model->alias]['id']);
        return true;
    }

}
